#!/usr/bin/runhaskell
{-|

  Script adapted from pandoc-plantuml-filter by Kurt Bonne
  Original source at https://github.com/kbonne/pandoc-plantuml-filter.git

  This script is meant to be run by pandoc executed by the pandoc_reader pelican plugin.
  I've changed output paths to be compatibile with pelican output structure.

  If using the pandoc_reader pelican plugin with this script, the plantuml plugin is not necessary.

  Installation:
  -------------
    This script requires Haskell, but if you are using pandoc, it's already installed :-)
    Copy this file in your pelican project, in the same directory of pelicanconf.py, and make sure it is executable.

    In the pelicanconf.py configure the need plugins:

      PLUGINS = ['pandoc_reader']
      PANDOC_ARGS = ['--filter=pandoc-plantuml']

    If this script will be putted in a different location, adapt the PANDOC_ARGS value.

  Usage:
  ------
    In Markdown posts use the following syntax to include PlantUML diagrams:

    ```plantuml
    @startuml
       Alice -> Bob: Authentication Request
       Bob --> Alice: Authentication Response

       Alice -> Bob: Another authentication Request
       Alice <-- Bob: another authentication Response
    @enduml
    ```

    Rendered images will bu put in the output/images folder.
-}

import Text.Pandoc.JSON
import Data.ByteString.Lazy (hGetContents, hPut)
import Data.ByteString.Lazy.UTF8 (fromString)
import Data.Digest.Pure.SHA (sha1, showDigest)
import System.IO (hClose, hPutStr, IOMode(..), openBinaryFile, hPutStrLn, stderr)
import System.Process
import System.Directory

processBlocks :: Block -> IO Block
processBlocks b =
  case b of
    CodeBlock (_ , ["plantuml"], _) content -> plantUMLToImg content
    _ -> return b

plantUMLToImg :: String -> IO Block
plantUMLToImg content =  do
  path <- renderImage content
  
  --hPutStrLn stderr "dopo renderImage"

  return $ Para [Image [] (path, "")]

renderImage :: String -> IO String
renderImage content = do
  createDirectoryIfMissing (True) "output/images"
  let path = uniqueName content ++ ".png"
  (Just hIn, Just hOut, _, _) <-
    createProcess (proc "plantuml" ["-pipe", "-tepg"]){ std_in = CreatePipe,
                                                        std_out = CreatePipe }
  hPutStr hIn content
  hClose hIn

  let outPath = "output/images/" ++ path
  hFile <- openBinaryFile outPath WriteMode
  img <- hGetContents hOut
  hPut hFile img

  hClose hFile
  hClose hOut

  let imgPath = "images/" ++ path

  return imgPath

uniqueName :: String -> String
uniqueName = showDigest . sha1 . fromString

main :: IO ()
main = toJSONFilter processBlocks
